const random=(min,max)=>Math.trunc(Math.random() * (max - min + 1) + min)

class Planewar{
    constructor(obj){
     this.data=obj
     this.$=jQuery
     this.difficult=['简单模式','一般模式','困难模式','地狱模式']
     //敌机出现各种飞机的概率
     this.mod=['small','small','small','big']
     //敌机生成速度
     this.enemySpeed=[700,600,500,400]
     //子弹的生成速度
     this.biuSpeed=[300,250,200,150]
     
     this.title='全民飞机大战v2.0'
     //敌机生成器的ID
        this.enemyTimer=0
     //子弹的定时器ID
       this.biuTime=0
      //记录分数
       this.score=0
       //子弹威力
       this.biupower= 1
      //敌机血条
       this.enemyHP={
        'big':{
          hp:3
        },
        'small':{
          hp:1
        }
       }
     //游戏挂载点
     this.app=this.$(this.data.app)

     this._init()
    }
  //初始化游戏界面
    _init(){
    //清楚游戏界面
     this.app.html("")
        this.app.css({
            width:this.data.width,
            height:this.data.height,
            margin:'20px auto',
            'box-shadow':'0 0 3px rgba(0,0,0,.4)',
            background:'url(./img/bg0.jpg) no-repeat center/cover',
            position:'relative',
            overflow:'hidden'
        })

     //创建游戏标题
     let $h1=$(`<h1>${this.title}</h1>`)
     this.app.append($h1)

     //创建难度模式按钮
     for(let i=0;i<this.difficult.length;i++){
         let $option=this.$(`<div class='option'>${this.difficult[i]}</div>`)

         $option.click(e=>{
            this.startGame(i,e)  
         })
         this.app.append($option)
     }
     }

     //启动游戏
     startGame(opt,event){
         this.app.html('')

         let $music=this.$('<audio src="./audio/game_music.mp3" loop="true"></audio>')
         this.app.append($music)
           this.$('document').ready(()=>{$music.get(0).play()})

         //创建分数记录
         let $record=this.$('<div class="record">0<div>')
         this.app.append($record)
         //设置不同模式的背景图
         this.app.css('background-image',`url(./img/bg${opt+1}.jpg)`)
       //opt:0 简单模式 1 一般模式 2 困难模式 3地狱模式

       //生成我方飞机
       this.myPlane(event,opt,$record)

       //调用敌机生成
       this.enemyTimer = setInterval(()=>{
        let m = this.mod[Math.trunc(Math.random() * this.mod.length)]
          this.enemy(m,$record)
       },this.enemySpeed[opt])

    }

    //生成敌方飞机  
    enemy(mod,$record){
      let $enemy=this.$(`<div class="enemy ${mod}" data-hp="${this.enemyHP[mod].hp}"></div>`).append(`<img 
      src="./img/enemy_${mod}.png">`)
      let $hp=this.$(`<div class="hp" data-thp="${this.enemyHP[mod].hp}"><div></div></div>`)

      $enemy.append($hp)
      this.app.append($enemy)
      $enemy.css({
          left:random(0,this.data.width-$enemy.width()),
          top:0
      }) 

     let speed=random(3,5)
     //控制飞机下落
     let run=()=>{
      let top=$enemy.position().top + speed
      $enemy.css('top',top)

      //需要跟子弹检测碰撞
       for(let i=0;i<globalThis.$('.biu').length;i++){
           let $biu=this.$('.biu').eq(i) 
           if($biu.parent().length && this.isDuang($enemy,$biu)){
         //记录分数
            this.recordScore($enemy,$record)
               $biu.remove()
               
               if($enemy.data('hp') <=0){
                 //读取该飞机的定位值，确定爆炸位置
                 this.boom($enemy)
                 $enemy.remove()
               }
           }
       }

      

      if(top < this.data.height){
        $enemy.parent().length && requestAnimationFrame(run)
      }else{
        $enemy.remove()
      }
     }
     run()
    }

    //生成我方飞机
    myPlane(e,opt,$record){ 
      let planeH=0
      let planeW=0

      let $bullet=this.$('<audio src="./audio/bullet.mp3"></audio>')
      let $plane=$('<div class="myPlane"></div>')
      let $img=$('<img class="plane-img" src="./img/plane_1.png">')
      $plane.append($img)
      this.app.append($plane)
      this.app.append($bullet)
    
      let appOffset=this.app.offset()


      $img.on('load',()=>{
          planeH=$plane.height()
          planeW=$plane.width()

          let left=e.pageX - appOffset.left - planeW / 2
          let top=e.pageY - appOffset.top - planeH / 2
 
          $plane.css({
              top,
              left
          })

          this.biuTime=setInterval(this.biu.bind(this),this.biuSpeed[opt],$plane,$bullet)
      })
       
      this.$(document).mousemove(e=>{
         let left=e.pageX - appOffset.left - planeW / 2
         let top=e.pageY - appOffset.top - planeH / 2

         top=Math.max(0,top)
         top=Math.min(top,this.data.height - planeH)
         left=Math.max(0 - planeW / 2,left)
         left=Math.min(left,this.data.width - planeW / 2)

         $plane.css({
             top,
             left
         })

         //需要跟我方飞机检测碰撞
         for(let i=0;i<globalThis.$('.enemy').length;i++){
          let $enemy=this.$('.enemy').eq(i)
          if($enemy.parent().length && this.isDuang($enemy,$plane)){
              $plane.remove()
              $enemy.remove()
              let $over=this.$('<audio src="./audio/game_over.mp3"></audio>')
              this.app.append($over)
              $over.get(0).play()
              $over.get(0).addEventListener('ended',()=>{this.gameover($record)},false)
          }
      }
      })
    }
   //生成子弹
   biu($plane,$bullet){
     let $biu=this.$('<img class="biu" src="./img/fire.png">')
     this.app.append($biu)
     $biu.css({
        left: $plane.position().left + $plane.width() / 2 - $biu.width() / 2,
        top: $plane.position().top - $biu.height()
     })
     $bullet.get(0).play()
   //控制子弹上升
     let run=()=>{
        let top=$biu.position().top - 8
        $biu.css('top',top)

        if(top > 0 ){
            $biu.parent.length && requestAnimationFrame(run)
          }else{
            $biu.remove()
          }
       }
       
       run()
   }

   //检测碰撞  false:未碰撞 true:碰撞了
   isDuang(a,b){
     let res=false

     let {top:t1,left:l1}=a.position()
     let b1=t1 + a.height()
     let r1=l1 + a.width()

     let {top:t2,left:l2}=b.position()
     let b2=t2 + b.height()
     let r2=l2 + b.width()
     
     res= b2 < t1 || t2 > b1 || r2 < l1 || l2 > r1

     return !res
   }
  //游戏分数界面
   gameover($record){
     this.app.html('')
     clearInterval(this.enemyTimer)
     clearInterval(this.biuTime)

     let $score=this.$(`<div class="score">最终得分：<p>${$record.html()}</p></div>`)
     this.app.append($score)

     let $again=this.$('<div class="again">再来一次</div>')

       $again.on('click',()=>{
         this._init()
       })
     this.app.append($again)
     this.score=0
   }

   //统计分数
   recordScore($enemy,$record){
    let isBig = $enemy.hasClass('big')

      if(isBig){
         let restHp=$enemy.data('hp') - this.biupower
        if(restHp>0){
           $enemy.data('hp',restHp)
           let $hp=$enemy.children('.hp')
           $hp.children('div').width((restHp/$hp.data('thp')) * $hp.width())
        }else{
          this.score +=3
          $enemy.data('hp',0)
        }
        
      }else{
        this.score ++
        $enemy.data('hp',0)
      }
      $record.html(this.score)
   }

   //boo图
   boom($enemy){
    let position=$enemy.position()
    let isbig=$enemy.hasClass('big')
    let $boom=this.$(`<img src="./img/boom_${isbig ? 'big' : 'small'}.png">`)
    position.width=$enemy.width()
    position.height=$enemy.height()
    position.position='absolute'
    $boom.css(position)

    $boom.fadeTo(250,0.5).fadeTo(250,1).fadeTo(250,0.5).fadeTo(250,1,()=>{
      $boom.remove()
    })
    this.app.append($boom)
   }
}